﻿

#include <iostream>
#include <windows.h>
#include <string>
#include <vector>
#include <conio.h>
#include <ctime>
#include <fstream>
using namespace std;

// 在全局变量区添加最高分变量
int maxScore = 0;

// 控制台颜色设置
enum ConsoleColor {
    BLACK = 0,
    BLUE = 1,
    GREEN = 2,
    CYAN = 3,
    RED = 4,
    MAGENTA = 5,
    BROWN = 6,
    LIGHTGRAY = 7,
    DARKGRAY = 8,
    LIGHTBLUE = 9,
    LIGHTGREEN = 10,
    LIGHTCYAN = 11,
    LIGHTRED = 12,
    LIGHTMAGENTA = 13,
    YELLOW = 14,
    WHITE = 15
};

// 游戏状态
enum E_SceneType {
    Begin,
    Game,
    End
};

// 方向枚举
enum Direction {
    UP, DOWN, LEFT, RIGHT
};

// 点结构
struct Point {
    int x, y;
    Point(int x = 0, int y = 0) : x(x), y(y) {}
};

// 添加速度相关变量
int sleepTime = 320;  // 初始时间间隔（毫秒），x速度是y的2倍通过方向速度计算实现
int baseScore = 2;    // 基础得分（根据速度动态调整）

// 设置控制台文本颜色
void setTextColor(ConsoleColor color) {
    HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
    SetConsoleTextAttribute(hConsole, color);
}

// 设置控制台光标位置
void setCursorPosition(int x, int y) {
    COORD coord = { (SHORT)x, (SHORT)y };
    SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);
}

// 绘制横向墙壁
void RowDrawWall(int y) {
    setTextColor(RED);
    for (int x = 0; x < 100; x++) {
        setCursorPosition(x, y);
        cout << "■";
    }
}

// 绘制纵向墙壁
void LineDrawWall(int x) {
    setTextColor(RED);
    for (int y = 0; y < 40; y++) {
        setCursorPosition(x, y);
        cout << "■";
    }
}

// 文件操作函数
void File_Out(int newScore) {
    // 只有当新分数超过当前最高分时才更新
    if (newScore > maxScore) {
        ofstream outFile("highscore.dat", ios::binary);
        if (outFile) {
            maxScore = newScore;
            outFile.write(reinterpret_cast<char*>(&maxScore), sizeof(maxScore));
        }
        outFile.close();
    }
}

void File_In() {
    ifstream inFile("highscore.dat", ios::binary);
    if (inFile) {
        inFile.read(reinterpret_cast<char*>(&maxScore), sizeof(maxScore));
    }
    else {
        maxScore = 0;  // 文件不存在时初始化最高分为0
    }
    inFile.close();
}

//绘制贪吃蛇图案（用于开始和结束界面）
//void drawSnakePattern() {
//    // 蛇头（红色）
//    setTextColor(LIGHTRED);
//    setCursorPosition(5, 5); cout << "        ▄▄▄▄▄▄        ";
//    setCursorPosition(5, 6); cout << "      █████████      ";
//    setCursorPosition(5, 7); cout << "    ▄██▀     ████▄    ";
//    setCursorPosition(5, 8); cout << "   ██▀       ███▄   ";
//    setCursorPosition(5, 9); cout << "  ██    ▄▄▄  ██  ";
//    setCursorPosition(5, 10); cout << " ██▄            ██ ";
//    setCursorPosition(5, 11); cout << " ███▄▄▄▄▄▄▄▄▄▄██ ";
// 蛇身（绿色渐变）
//    setTextColor(LIGHTGREEN);
//    setCursorPosition(5, 12); cout << "  ████████████ ";
//
//    setCursorPosition(5, 13); cout << "      ███    ";
//
//    setTextColor(GREEN);
//    setCursorPosition(5, 14); cout << "      ███       ";
//}

// 初始化贪吃蛇地图
void initSnakeMap() {
    // 清屏
    system("cls");

    // 调整控制台窗口大小
    string cmd = "mode con cols=101 lines=41";
    if (system(cmd.c_str()) == -1) {
        cerr << "Failed to set console size." << endl;
        return;
    }

    // 隐藏光标
    CONSOLE_CURSOR_INFO cursorInfo;
    cursorInfo.dwSize = 1;
    cursorInfo.bVisible = FALSE;
    if (!SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cursorInfo)) {
        cerr << "Failed to hide cursor." << endl;
        return;
    }

    // 绘制地图边界
    RowDrawWall(0);
    RowDrawWall(39);
    LineDrawWall(0);
    LineDrawWall(99);

    // 重置文本颜色
    setTextColor(WHITE);
}

// 开始或结束场景函数
void BeginorEndSence(E_SceneType& nowSence, int currentScore = 0) {
    bool IsOk = false;
    int nowIndex = 0;
    // 在显示前先读取最新最高分
    File_In();

    // 隐藏光标 
    CONSOLE_CURSOR_INFO cursorInfo;
    cursorInfo.dwSize = 1;
    cursorInfo.bVisible = FALSE;
    SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cursorInfo);

    // 清除屏幕
    system("cls");

    // 修改显示最高分部分
    setTextColor(LIGHTRED);
    setCursorPosition(43, 11);
    cout << "您的最高分: " << maxScore << "    ";  // 添加空格清除旧内容
    // 显示标题（居中）
    setTextColor(LIGHTGREEN);
    string title = (nowSence == Begin) ? "" : "游戏结束";
    setCursorPosition(50 - title.length() / 2, 5);
    cout << title << endl;

    // 显示副标题（居中）
    setTextColor(WHITE);
    string subtitle = (nowSence == Begin) ? "欢迎来到贪吃蛇游戏" : "感谢游玩贪吃蛇游戏";
    setCursorPosition(50 - subtitle.length() / 2, 7);
    cout << subtitle << endl;

    setTextColor(LIGHTRED);
    setCursorPosition(43, 11);
    cout << "您的最高分: " << maxScore << endl;

    // 绘制蛇图案
    /*drawSnakePattern();*/

    while (true) {
        // 显示选项（居中）
        setTextColor(nowIndex == 0 ? LIGHTRED : WHITE);
        string option1 = (nowSence == Begin) ? "开始游戏" : "回到主菜单";
        setCursorPosition(50 - option1.length() / 2, 15);
        cout << option1;

        setTextColor(nowIndex == 1 ? LIGHTRED : WHITE);
        string option2 = "结束游戏";
        setCursorPosition(50 - option2.length() / 2, 17);
        cout << option2;

        // 处理键盘输入
        char key = _getch();
        switch (key) {
        case 'w':
        case 'W':
        case 72: // 上箭头
            nowIndex--;
            if (nowIndex < 0) nowIndex = 0;
            break;

        case 's':
        case 'S':
        case 80: // 下箭头
            nowIndex++;
            if (nowIndex > 1) nowIndex = 1;
            break;

        case '\r': // 回车键
            if (nowIndex == 1) {
                exit(0); // 结束游戏
            }
            else {
                IsOk = true;
            }
            break;
        }

        if (IsOk) {
            nowSence = (nowSence == Begin) ? Game : Begin;
            break;
        }
    }
}

// 绘制蛇
void drawSnake(const vector<Point>& snake) { 
    // 绘制蛇身
    setTextColor(LIGHTGREEN);
    for (size_t i = 1; i < snake.size(); i++) {
        setCursorPosition(snake[i].x, snake[i].y);
        cout << "◆";
    }

    // 绘制蛇头
    setTextColor(LIGHTRED);
    setCursorPosition(snake[0].x, snake[0].y);
    cout << "★";
}

// 绘制食物
void drawFood(const Point& food) {
    setTextColor(YELLOW);
    setCursorPosition(food.x, food.y);
    cout << "●";
}

// 检查是否吃到食物
bool checkEat(const Point& head, const Point& food) {
    return head.x == food.x && head.y == food.y;
}

// 检查是否碰撞
bool checkCollision(const vector<Point>& snake) {
    // 检查是否撞到墙壁
    if (snake[0].x <= 0 || snake[0].x >= 99 || snake[0].y <= 0 || snake[0].y >= 39)
        return true;

    // 检查是否撞到自己
    for (int i = 1; i < snake.size(); i++) {
        if (snake[0].x == snake[i].x && snake[0].y == snake[i].y)
            return true;
    }

    return false;
}

// 生成食物位置
Point generateFood(const vector<Point>& snake) {
    Point food;
    bool validPosition;

    do {
        validPosition = true;
        food.x = (rand() % 48) * 2 + 2;  // 确保x坐标为偶数（2-98）
        food.y = rand() % 38 + 1;

        // 确保食物不会生成在蛇身上
        for (const auto& segment : snake) {
            if (segment.x == food.x && segment.y == food.y) {
                validPosition = false;
                break;
            }
        }
    } while (!validPosition);

    return food;
}

// 加速函数
void speedUp() {
    if (sleepTime > 10) { // 防止低于最小间隔
        sleepTime -= 10;
        baseScore = max(1, baseScore + 2); // 得分至少为1，每次加速加2分
    }
}

// 减速函数
void speedDown() {
    if (sleepTime < 500) { // 限制最大间隔
        sleepTime += 30;
        baseScore = max(1, baseScore - 2); // 得分至少为1，每次减速减2分
        if (baseScore < 1) baseScore = 1; // 确保得分不为0
    }
}

// 游戏主循环
void gameLoop(int& finalScore) { // 添加输出参数
    // 初始化随机数种子
    srand(static_cast<unsigned int>(time(nullptr)));

    // 初始化蛇
    vector<Point> snake;
    snake.push_back(Point(50, 20)); // 蛇头
    snake.push_back(Point(48, 20));
    snake.push_back(Point(46, 20));
    snake.push_back(Point(44, 20));

    // 初始化食物
    Point food = generateFood(snake);

    // 初始化方向（x速度是y的2倍，通过方向处理实现）
    Direction direction = RIGHT;
    Direction nextDirection = RIGHT;

    // 初始化分数
    int score = 0;

    // 绘制初始状态
    initSnakeMap();
    drawSnake(snake);
    drawFood(food);

    // 显示分数和速度提示
    setTextColor(WHITE);
    setCursorPosition(10, 40);
    cout << "分数: " << score << "    ";
    setCursorPosition(30, 40);
    cout << "速度: " << sleepTime << "ms    ";
    setCursorPosition(50, 40);
    cout << "得分倍率: x" << baseScore << "    ";

    // 游戏主循环
    while (true) {
        // 处理键盘输入（添加F1/F2加速/减速）
        if (_kbhit()) {
            int key = _getch();
            if (key == 0 || key == 0xE0) {  // 处理扩展按键
                int extKey = _getch();
                switch (extKey) {
                case 59:  // F1
                    speedUp();
                    setCursorPosition(30, 40);
                    cout << "速度: " << sleepTime << "ms    ";
                    setCursorPosition(50, 40);
                    cout << "得分倍率: x" << baseScore << "    ";
                    break;
                case 60:  // F2
                    speedDown();
                    setCursorPosition(30, 40);
                    cout << "速度: " << sleepTime << "ms    ";
                    setCursorPosition(50, 40);
                    cout << "得分倍率: x" << baseScore << "    ";
                    break;
                }
            }
            else {
                switch (key) {
                case 'w':
                case 'W':
                case 72: // 上箭头
                    if (direction != DOWN) nextDirection = UP;
                    break;
                case 'S':
                case 's':
                case 80: // 下箭头
                    if (direction != UP) nextDirection = DOWN;
                    break;
                case 'a':
                case 'A':
                case 75: // 左箭头
                    if (direction != RIGHT) nextDirection = LEFT;
                    break;
                case 'd':
                case 'D':
                case 77: // 右箭头
                    if (direction != LEFT) nextDirection = RIGHT;
                    break;              
                case 27: // ESC键
                    return;
                }
            }
        }

        // 更新方向
        direction = nextDirection;

        // 计算移动步长（x轴速度是y轴的2倍）
        Point delta = { 0, 0 };
        switch (direction) {
        case UP:    delta.y = -1; break;
        case DOWN:  delta.y = 1;  break;
        case LEFT:  delta.x = -2; break; // x轴移动2格实现2倍速度
        case RIGHT: delta.x = 2;  break;
        }

        // 移动蛇
        Point newHead = { snake[0].x + delta.x, snake[0].y + delta.y };
        snake.insert(snake.begin(), newHead);

        // 检查是否吃到食物
        if (checkEat(newHead, food)) {
            score += baseScore; // 使用动态得分倍率

            // 显示更新信息
            setCursorPosition(10, 40);
            cout << "分数: " << score << "    ";
            setCursorPosition(30, 40);
            cout << "速度: " << sleepTime << "ms    ";
            setCursorPosition(50, 40);
            cout << "得分倍率: x" << baseScore << "    ";

            food = generateFood(snake);
            drawFood(food);
            speedUp(); // 吃食物自动加速
        }
        else {
            // 移除尾部
            setCursorPosition(snake.back().x, snake.back().y);
            cout << "  ";
            snake.pop_back();
        }

        // 绘制蛇
        drawSnake(snake);

        // 检查碰撞
        if (checkCollision(snake)) {
            setTextColor(RED);
            setCursorPosition(36, 20);
            cout << "游戏结束! 按任意键返回主菜单";
            _getch();
            return;
        }

        // 控制游戏速度（根据sleepTime延迟）
        Sleep(sleepTime);

        // 游戏结束前保存分数
        finalScore = score;
    }
}

int main() {
    E_SceneType nowSence = Begin;
    File_In();  // 程序启动时读取最高分

    while (true) {
        int finalScore = 0;
        switch (nowSence) {
        case Begin:
            BeginorEndSence(nowSence);
            break;
        case Game:
            gameLoop(finalScore);
            File_Out(finalScore);  // 游戏结束后尝试保存分数
            nowSence = End;
            break;
        case End:
            BeginorEndSence(nowSence, maxScore);  // 传递当前最高分
            break;
        }
    }

    return 0;
}